home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 41
/
Amiga Format CD41 (1999-06)(Future Publishing)(GB)[!][issue 1999-07].iso
/
-seriously_amiga-
/
cd-rom
/
acdb
/
src
/
acdb_cd.e
< prev
next >
Wrap
Text File
|
1999-04-28
|
16KB
|
675 lines
OPT MODULE,OSVERSION=37
OPT PREPROCESS,REG=5
/*
*-- AutoRev header do NOT edit!!
*
* Project : ACDB (AMIGA CD Base) - program obsîugujâcy CDDB
* File : acdb_cd.e
* Description : obsîuga CD przez SCSI
* Copyright : ©1998-1999, Piotr Gapiïski
* Author : Piotr Gapiïski
* Creation Date : 10.03.99
* Current version : 1.0
* Translator : AmigaE v3.3a
*
*-- REVISION HISTORY
*
* 1.0 (10.03.99)
* o reorganizacja procedur - lepsze ukrywanie danych i wydzielenie
* interfejsu uûytkownika
*
* 0.1 (22.12.98)
* o pierwsza wersja (BETA)
* obsîuga SCSI oparta na X3T9.2 WORKING DRAFT (7-SEP-93)
*
*/
MODULE 'exec/memory','exec/ports','exec/devices','exec/io','devices/scsidisk'
MODULE 'exec/nodes','dos/dos'
MODULE '*acdb_debug','*acdb_gui'
#ifdef DEBUG
MODULE 'tools/debug'
#define D(a,b) kputfmt(a,b)
#endif
#ifndef DEBUG
#define D(a,b)
#endif
->-
->- komendy SCSI (6, 10 i 12 bajtowe)
->-
OBJECT scsicmd6
opcode :CHAR
b1 :CHAR
b2 :CHAR
b3 :CHAR
b4 :CHAR
control :CHAR
ENDOBJECT
OBJECT scsicmd10
opcode :CHAR
b1 :CHAR
b2 :CHAR
b3 :CHAR
b4 :CHAR
b5 :CHAR
b6 :CHAR
b7 :CHAR
b8 :CHAR
control :CHAR
ENDOBJECT
OBJECT scsicmd12
opcode :CHAR
b1 :CHAR
b2 :CHAR
b3 :CHAR
b4 :CHAR
b5 :CHAR
b6 :CHAR
b7 :CHAR
b8 :CHAR
b9 :CHAR
b10 :CHAR
control :CHAR
ENDOBJECT
->-
->- track na CD (minuta, sekunda i ramka rozpoczëcia utworu)
->-
OBJECT msf
min :LONG
sec :LONG
frm :LONG
ENDOBJECT
CONST SCSI_CMD_TUR = $00,
SCSI_CMD_RZU = $01,
SCSI_CMD_RQS = $03,
SCSI_CMD_FMU = $04,
SCSI_CMD_RAB = $07,
SCSI_CMD_RD = $08,
SCSI_CMD_WR = $0A,
SCSI_CMD_SK = $0B,
SCSI_CMD_INQ = $12,
SCSI_CMD_MSL = $15,
SCSI_CMD_RU = $16,
SCSI_CMD_RLU = $17,
SCSI_CMD_MSE = $1A,
SCSI_CMD_SSU = $1B,
SCSI_CMD_RDI = $1C,
SCSI_CMD_SDI = $1D,
SCSI_CMD_PAMR = $1E,
SCSI_CMD_RCP = $25,
SCSI_CMD_RXT = $28,
SCSI_CMD_WXT = $2A,
SCSI_CMD_SKX = $2B,
SCSI_CMD_WVF = $2E,
SCSI_CMD_VF = $2F,
SCSI_CMD_RDD = $37,
SCSI_CMD_WDB = $3B,
SCSI_CMD_RDB = $3C
CONST SCSI_CMD_COPY = $18,
SCSI_CMD_COMPARE = $39,
SCSI_CMD_COPYANDVERIFY = $3A,
SCSI_CMD_CHGEDEF = $40,
SCSI_CMD_READSUBCHANNEL = $42,
SCSI_CMD_READTOC = $43,
SCSI_CMD_READHEADER = $44,
SCSI_CMD_PLAYAUDIO12 = $A5,
SCSI_CMD_PLAYAUDIOTRACKINDEX = $48,
SCSI_CMD_PAUSERESUME = $4B
CONST SENSE_LEN = 252,
MAX_DATA_LEN = 252,
MAX_TOC_LEN = 804
DEF scsidata:PTR TO CHAR, scsisense:PTR TO CHAR, tocbuffer:PTR TO CHAR
DEF scsimp:PTR TO mp, scsio:PTR TO iostd
DEF scsidevice:PTR TO CHAR, scsiunit:LONG
EXPORT OBJECT cdinfo OF ln ->- obiekt opisujâcy wîaôciwoôci pîyty kompaktowej
PRIVATE
cdtoc[100] :ARRAY OF msf ->- TOC pîyty w formacie MSF
idname[20] :ARRAY OF CHAR ->- nazwa pliku ID kompaktu
tracks :LONG ->- ile ôcieûek na pîycie
time :LONG ->- czas pîyty w sekundach
cddb :LONG ->- identyfikator CDDB
ENDOBJECT
EXPORT PROC cdSetup(device:PTR TO CHAR, unit) HANDLE
->-
->- inicjalizacja urzâdzenia SCSI obsîugiwanego przez device
->- dev_name/dev_id
->- dane wejôciowe nie sâ zapamiëtywane (buforowane)!
->- zwraca TRUE/FALSE
->-
DEF data:PTR TO CHAR, error
->-
->- zaalokuj sense, TOC i bufory
->- ustaw wskaúniki
->-
scsidevice := device
scsiunit := unit
data := AllocVec((MAX_DATA_LEN + MAX_TOC_LEN + SENSE_LEN), (MEMF_CHIP OR MEMF_CLEAR))
IF (data = NIL) THEN RETURN FALSE
scsidata := data
scsisense := (data + MAX_DATA_LEN)
tocbuffer := (scsisense + MAX_TOC_LEN)
->-
->- utwórz port i request
->-
scsimp := CreateMsgPort()
IF (scsimp = FALSE) THEN Raise('Unable to create message port!')
scsio := CreateIORequest(scsimp, (SIZEOF iostd))
IF (scsio = FALSE) THEN Raise('Unable to create IO request!')
->-
->- otwórz ûâdany device/unit
->-
error := OpenDevice(scsidevice, scsiunit, scsio, 0)
IF (error) THEN Throw('Unable to open %s, unit %ld (error %ld)!', [scsidevice, scsiunit, error, NIL])
RETURN TRUE
EXCEPT
->- IF (exception) THEN WriteF('\s!\n', stringFmt(exception, exceptioninfo))
cdCleanUp()
ENDPROC FALSE
EXPORT PROC cdCleanUp()
->-
->- procedura zwalniajâca wszystkie zaalkowane przez scsiSetup()
->- zasoby
->- nie zwraca ûadnych wartoôci
->-
DEF msg
IF (scsio)
->-
->- scsio,device jest AUTOMATYCZNIE niszczone podczas CloseDevice()
->-
IF (scsio.device) THEN CloseDevice(scsio)
DeleteIORequest(scsio)
ENDIF
IF (scsimp)
->-
->- przed usuniëciem portu naleûy pozbyê sië wszystkich zgromadzonych w nim
->- wiadomoôci (przy wyîâczonym multitaskingu)
->-
Forbid()
WHILE msg := GetMsg(scsimp) DO ReplyMsg(msg)
DeleteMsgPort(scsimp)
Permit()
ENDIF
IF (scsidata) THEN FreeVec(scsidata)
ENDPROC
EXPORT PROC cdRawInfo() HANDLE
->-
->- procedura allokujâca pamiëê na strukturë cdinfo
->- brak inicjalizacji
->- procedura zwraca wskaúnik na strukturë lub NIL
->-
DEF cd=NIL:PTR TO cdinfo
NEW cd
EXCEPT DO
ENDPROC cd
EXPORT PROC cdCreateInfo() HANDLE
->-
->- procedura wypeîniajâca strukturë cdinfo danymi dla dysku aktualnie
->- znajdujâcego sië w napëdzie (najpierw testowana jest fizycna obecnoôê dysku)
->- zwraca wskaúnik na zainicjowanâ strukturë cdinfo lub NIL
->-
DEF cd=NIL:PTR TO cdinfo
->-
->- TOC i iloôê ôcieûek
->-
IF (cd := cdRawInfo())=NIL THEN Raise()
cd.tracks := readtocmsf(cd.cdtoc)
IF (cd.tracks = 0) THEN Raise('Cannot read TOC!')
->-
->- CDDB i time
->-
D('[CDCREATEINFO] make cd struct\n', NIL)
cd.cddb := cddb(cd.tracks, cd.cdtoc)
->-
->- tutaj (chyba) nie moûna uûyê funkcji cdTime() - nie sprawdzaîem
->- ale to poniûej dziaîa
->-
cd.time := (
((cd.cdtoc[cd.tracks].min * 60) + cd.cdtoc[cd.tracks].sec) -
((cd.cdtoc[0].min * 60) + cd.cdtoc[0].sec)
)
IF fileid(cd.idname)=FALSE THEN Raise('Cannot compute CDID file name!')
RETURN cd
EXCEPT
IF (cd) THEN cdFreeInfo(cd)
D('[CDCREATEINFO] error \s\n', [exception, NIL])
ENDPROC NIL
EXPORT PROC cdFreeInfo(cd:PTR TO cdinfo)
->-
->- procedura zwalniajâca caîkowitâ pamiëê zajmowanâ przez opis pîyty kompaktowej
->- nie zwraca ûadnych wartoôci
->-
->-
D('[CDFREEINFO] dispose cd struct\n', NIL)
END cd
ENDPROC
EXPORT PROC cdWriteInfo(cd:PTR TO cdinfo, handle)
->-
->- procedura zapisujâca identyfikator pîyty do pobrania
->- wymaga podania otwartego handle do pliku
->- procedura nie zamyka przekazanego deskryptora pliku
->- zwraca TRUE/FALSE
->-
DEF rc, size, ws
IF (handle)
->-
->- zapis danych do pliku
->- dodatkowo nastâpi sprawdzenie poprawnoôci zapisu
->-
D('[CDWRITEINFO] write cd to handle $\h\n', [handle, NIL])
size := (SIZEOF cdinfo) - (SIZEOF ln)
ws := Write(handle, cd + (SIZEOF ln), size)
rc := IF (ws = size) THEN TRUE ELSE FALSE
ELSE
rc := FALSE
ENDIF
ENDPROC rc
EXPORT PROC cdReadInfo(cd:PTR TO cdinfo, handle)
->-
->- procedura odczytujâca identyfikator pîyty do pobrania
->- wymaga podania otwartego handle do pliku
->- procedura nie zamyka przekazanego deskryptora pliku
->- zwraca TRUE/FALSE
->-
DEF rc, size, rd
IF (handle)
->-
->- odczyt danych do pliku
->- dodatkowo nastâpi sprawdzenie poprawnoôci odczytu
->-
D('[CDREADINFO] read cd from handle $\h\n', [handle, NIL])
size := (SIZEOF cdinfo) - (SIZEOF ln)
rd := Read(handle, cd + (SIZEOF ln), size)
rc := IF (rd = size) THEN TRUE ELSE FALSE
ELSE
rc := FALSE
ENDIF
ENDPROC rc
EXPORT PROC cdInquire()
->-
->- procedura pobierajâca i wyôwietlajâca dane zapisane w CD-ROM'ie przez producenta
->- nie zwraca ûadnych wartoôci
->-
DEF command:PTR TO scsicmd6, rc
command := [SCSI_CMD_INQ,0,0,0,0,0]:scsicmd6
command.b4 := MAX_DATA_LEN
rc := doscsicmd(scsidata, MAX_DATA_LEN, command, (SIZEOF scsicmd6), (SCSIF_READ OR SCSIF_AUTOSENSE))
IF (rc = 0)
->-
->- pokaû odebrane dane
->-
guiInformUser('Software driver: %s, unit %ld\nType (5): CD-ROM device\nVendor: %.8s\nProduct: %.16s\nRevision: %.4s',
' _Ok ',
[scsidevice, scsiunit, (scsidata + 8), (scsidata + 16), (scsidata + 32), NIL])
ELSE
DisplayBeep(NIL)
ENDIF
ENDPROC
EXPORT PROC cdCheck()
->-
->- procedura sprawdzajâca czy device/unit faktycznie obsîuguje CD-ROM
->- zwraca TRUE/FALSE
->-
DEF command:PTR TO scsicmd6, rc
command := [SCSI_CMD_INQ,0,0,0,0,0]:scsicmd6
command.b4 := MAX_DATA_LEN
rc := doscsicmd(scsidata, MAX_DATA_LEN, command, (SIZEOF scsicmd6), (SCSIF_READ OR SCSIF_AUTOSENSE))
IF (rc=0)
->-
->- musi zwróciê 5, w przeciwnym razie nie jest to CD-ROM
->-
RETURN IF (scsidata[] AND $1F)=5 THEN TRUE ELSE FALSE
ELSE
DisplayBeep(NIL)
ENDIF
ENDPROC FALSE
EXPORT PROC cdEject(eject=TRUE)
->-
->- procedura zamykajâca/otwierajâca kieszeï napëdu
->- zwraca 0/kod bîëdu (< 0)
->-
DEF command:PTR TO scsicmd6, rc
command := IF (eject) THEN [SCSI_CMD_SSU,0,0,0,2,0]:scsicmd6 ELSE [SCSI_CMD_SSU,0,0,0,3,0]:scsicmd6
rc := doscsicmd(scsidata, MAX_DATA_LEN, command, (SIZEOF scsicmd6), (SCSIF_READ OR SCSIF_AUTOSENSE))
ENDPROC rc
EXPORT PROC cdTrackTime(cd:PTR TO cdinfo, track)
->-
->- procedura pobierajâca czas trwania okreôlonego utworu
->- zwraca czas w sekundach lub FALSE
->-
DEF time
IF (track >= cd.tracks) THEN RETURN FALSE
time := ((cd.cdtoc[track + 1].frm) - (cd.cdtoc[track].frm))/75
ENDPROC time
EXPORT PROC cdTime(cd:PTR TO cdinfo)
->-
->- procedura pobierajâca czas trwania caîej pîyty
->- zwraca czas w sekundach
->-
DEF time
->- time := ((cd.cdtoc[cd.tracks].frm) - (cd.cdtoc[0].frm))/75
time := cd.time
ENDPROC time
EXPORT PROC cdTrackOffset(cd:PTR TO cdinfo, track)
->-
->- procedura pobierajâca offset utworu wzglëdem poczâtku pîyty
->- zwraca offset lub FALSE
->-
DEF rc
IF (track >= cd.tracks) THEN RETURN FALSE
rc := cd.cdtoc[track].frm
ENDPROC rc
EXPORT PROC cdFileId(cd: PTR TO cdinfo)
->-
->- procedura pobierajâca nazwë identyfikatora pod jakâ zostanie
->- zapisany plik opisu pîyty
->-
DEF name
name := IF (cd) THEN cd.idname ELSE NIL
ENDPROC name
EXPORT PROC cdId(cd:PTR TO cdinfo) IS cd.cddb
EXPORT PROC cdTracks(cd:PTR TO cdinfo) IS cd.tracks
->-
->- prywatne
->- procedury wspomagajâce obsîugë CD-ROM'u
->-
PROC readtocmsf(msf:PTR TO msf)
->-
->- procedura odczytujâca TOC (table of contents) CD-ROMu - 804bajty
->- w formacie MSF (min, sec, frame)
->- procedura nie rozróûnia tracków AUDIO od DATA
->- zwraca liczbë ôcieûek na pîycie oraz kopiuje TOC pîyty do przekazanego
->- jako parametr bufora (o wielkoôci 100 * SIZEOF msf)
->-
DEF command:PTR TO scsicmd10, rc
DEF tocsize, tocptr:PTR TO CHAR, tocnumtracks=0
DEF cdtoc[100]:ARRAY OF msf
command := [SCSI_CMD_READTOC,0,0,0,0,0,0,$03,$24,0]:scsicmd10
command.b1 := 2 ->- MSF
rc := doscsicmd(tocbuffer, MAX_TOC_LEN, command, (SIZEOF scsicmd10), (SCSIF_READ OR SCSIF_AUTOSENSE))
IF (rc=0)
->-
->- oblicz realnâ wielkoôê TOC
->-
tocsize := Shl(tocbuffer[], 8) + tocbuffer[1]
IF (tocsize >= 2) THEN tocsize := tocsize - 2
tocptr := tocbuffer + 4
tocnumtracks := 0
WHILE (tocptr < (tocbuffer + 4 + tocsize))
->-
->- pobieraj wszystkie ôcieûki bez wzglëdu na to czy jest to audio czy data!
->- ôcieûki sâ opisane w formacie MSF
->-
cdtoc[tocnumtracks].min := tocptr[5]
cdtoc[tocnumtracks].sec := tocptr[6]
cdtoc[tocnumtracks].frm := ((tocptr[5]*60)+(tocptr[6]))*75+tocptr[7]
tocptr := tocptr + 8
tocnumtracks++
ENDWHILE
tocnumtracks--
ENDIF
->-
->- skopiuj dane przechowywane lokalnie do bufora wskazywanego przez msf
->-
CopyMem(cdtoc, msf, (100 * SIZEOF msf))
ENDPROC tocnumtracks
PROC fileid(cdid: PTR TO CHAR)
->-
->- procedura tworzâca ID pliku do CDplayera (format zgodny z SCDP)
->- wynik kopiuje do bufora przekazanego do procedury
->- brak rozróûniania ôcieûek audio i data
->- zwraca TRUE/FALSE oraz gdy TRUE to kopiuje identyfikator do bufora przekazanego
->- jako parametr (minimum 20 bajtów)
->-
DEF command:PTR TO scsicmd10, rc
DEF tocsize, tocptr:PTR TO CHAR, tocnumtracks=0
DEF toctrackaddr[256]: ARRAY OF LONG
DEF tmp[20]:STRING
command := [SCSI_CMD_READTOC,0,0,0,0,0,0,$03,$24,0]:scsicmd10
rc := doscsicmd(tocbuffer, MAX_TOC_LEN, command, (SIZEOF scsicmd10), (SCSIF_READ OR SCSIF_AUTOSENSE))
IF (rc = 0)
->-
->- oblicz realnâ wielkoôê TOC
->-
tocsize := Shl(tocbuffer[], 8) + tocbuffer[1]
IF (tocsize >= 2) THEN tocsize := tocsize - 2
tocptr := tocbuffer + 4
tocnumtracks := 0
WHILE (tocptr < (tocbuffer + 4 + tocsize))
->-
->- obliczenie identyfikatora
->-
toctrackaddr[tocnumtracks] := (Shl(tocptr[4], 24) OR Shl(tocptr[5], 16) OR Shl(tocptr[6], 8) OR (tocptr[7]))
->-
->- brak rozróûniania ôcieûek audio i data
->-
->- tocflags[tocnumtracks] := IF ((tocptr+1) AND $04) THEN 1 ELSE 0
->-
tocnumtracks++
tocptr := tocptr + 8
ENDWHILE
tocnumtracks--
stringFmt(tmp, 'ID%02ld%06lx%06lx', [tocnumtracks, toctrackaddr[2], toctrackaddr[tocnumtracks], NIL])
AstrCopy(cdid, tmp, 20)
ENDIF
ENDPROC (rc = 0)
PROC doscsicmd(data:PTR TO CHAR,datasize,cmd:PTR TO CHAR,cmdsize,flags)
->-
->- procedura wykonujâca okreôlonâ komendë SCSI
->- zwraca 0 w przypadku sukcesu lub kod bîëdu (< 0)
->-
DEF scsicmd:scsicmd
scsio.length := (SIZEOF scsicmd)
scsio.data := scsicmd
scsio.command := HD_SCSICMD
scsicmd.data := data
scsicmd.length := datasize
scsicmd.senseactual := 0
scsicmd.senselength := SENSE_LEN
scsicmd.sensedata := scsisense
scsicmd.command := cmd
scsicmd.cmdlength := cmdsize
scsicmd.flags := flags
scsicmd.status := 0
DoIO(scsio)
ENDPROC (scsio.error)
PROC cddb(trks, cdtoc:PTR TO msf)
->-
->- procedura wyznaczajâce CDID kompaktu na potrzeby CDDB
->- zaczerpniëta z CDDB howto (www.cddb.com)
->- obliczony identyfikator MUSI byê przedstawiany jako 8-mio cyfrowa liczba
->- zapisana w kodzie ASCII (w kodzie szesnastkowym)
->-
DEF i=0, t=0, n=0
WHILE (i < trks)
n := n + cddbsum(((cdtoc[i].min) * 60) + (cdtoc[i].sec))
i++
ENDWHILE
n := Shl(Mod(n,255), 24)
t := (((cdtoc[trks].min)*60)+(cdtoc[trks].sec)) - (((cdtoc[0].min)*60)+(cdtoc[0].sec))
t := Shl(t, 8)
ENDPROC (n OR t OR trks)
PROC cddbsum(n: LONG)
->-
->- procedura pomocnicza wyznaczania CDDB
->-
DEF ret=0, a
WHILE (n > 0)
a := Mod(n, 10)
ret := (ret + a)
n := (n / 10)
ENDWHILE
ENDPROC ret